/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csp;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Pablo
 */
public class Backtracking extends AlgortimoCSP{

    @Override
    public boolean resolver(CSP problema) {
           
        if(this.heuValor instanceof VMR){
        VMR valorAux= (VMR) this.heuValor;
        valorAux.setVerificador((ExpertoRestriccionesAntena)problema.getVerificadorRestricciones());
       }
       
        this.verificadorRestricciones = problema.getVerificadorRestricciones();
        this.medidasRendimiento.inicializarRuntime();
        boolean resultadoBusqueda=backtracking(problema);
        this.medidasRendimiento.finalizarRuntime();
        return resultadoBusqueda;
    
    }

    public Backtracking(HeuristicaValor heuValor, HeuristicaVariable heuVar){
        this.heuValor = heuValor;
        this.heuVar = heuVar;
        this.medidasRendimiento = new Rendimiento();
    }
    
     private boolean backtracking(CSP problema){
        this.medidasRendimiento.incRecursiones();
         if (problema.getVariablesNoAsignadas() == 0) {
           // return verificadorRestricciones.factible(problema);
            return true;
        } else {
            Variable variableActual = heuVar.getNextVariable(problema); //Heuristica selecciona variable
            if (variableActual != null) {
                List<Valor> valoresPosibles = variableActual.getValoresPosibles();
                List<Valor> auxValoresOrdenados = new ArrayList<Valor>(heuValor.ordenarValores(valoresPosibles,variableActual, problema.getDominio().size()));

                for (Valor valorAasignar : auxValoresOrdenados) {

                    variableActual.setAsignado(valorAasignar);
                     this.medidasRendimiento.incBackTracks();
                    //verificar si hace falta al debuggear
                    //problema.getVariables().get(problema.variablePorAsignar).setAsignado(valorAasignar);
                    if (verificadorRestricciones.factible(problema)) {

                        //Se remueve el valor asignado del dominio del resto de las variables
                        for (Variable var : problema.getVariables()) {
                           // if(var.getAsignado() == null){
                            var.getValoresPosibles().remove(valorAasignar);
                            //}
                        }
//                        if (comprobarHaciaAdelante(variableActual, problema)){
                            if (this.backtracking(problema)) {
                                return true;
                            } else {
                           //devuelve los valores quitados a los dominios
                            for (Variable var : problema.getVariables()) {
                            //if(var.getAsignado() == null){
                            var.getValoresPosibles().add(valorAasignar);
                            //}
                        }
                        }

//                        } else {
//                           //devuelve los valores quitados a los dominios
//                            for (Variable var : problema.getVariables()) {
//                            //if(var.getAsignado() == null){
//                            var.getValoresPosibles().add(valorAasignar);
//                            //}
//                        }
//                        }
                    }
                }
               variableActual.setAsignado(null);
              
               return false;
            }
            return false;
        }
    }
}
